package com.longtop.sp.mapdao.impl;

import java.io.ByteArrayInputStream;
import java.io.CharArrayReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.longtop.sp.mapdao.Lob;

/**
 * Lob接口定义了8个方法，CLOB和BLOB，字段名和序号，读和写，3个变化的因素，是2的3次方。
 * 此抽象类提供一些实用方法，将字段名和序号的差异消除，子类只需要实现4个方法。同时，提供了数据校验功能。
 * 如果子类继承此抽象类不方便或有困难，也可以直接实现Lob接口。
 * 
 * @author 赵斌 2003-6-23
 * @author 胡长城 2003-6-23
 * @version $Revision: 1.2 $
 */
abstract public class AbstractLob implements Lob {
	public void writeBLOB(ResultSet rs, String fieldName, Object o)
			throws SQLException, IOException {
		if (o == null) {
			throw new SQLException("向BLOB字段中写数据，数据不可以是null。");
		}

		if (o instanceof byte[]) {
			writeBLOB(rs, rs.getBlob(fieldName), new ByteArrayInputStream(
					(byte[]) o));
		} else if (o instanceof InputStream) {
			writeBLOB(rs, rs.getBlob(fieldName), (InputStream) o);
		} else {
			throw new SQLException(
					"向BLOB字段中写数据，您只可以使用byte[]或InputStream或FormFile对象。");
		}
	}

	public void writeBLOB(ResultSet rs, int idx, Object o) throws SQLException,
			IOException {
		if (o == null) {
			throw new SQLException("向BLOB字段中写数据，数据不可以是null。");
		}

		if (o instanceof byte[]) {
			writeBLOB(rs, rs.getBlob(idx), new ByteArrayInputStream((byte[]) o));
		} else if (o instanceof InputStream) {
			writeBLOB(rs, rs.getBlob(idx), (InputStream) o);
		} else {
			throw new SQLException(
					"向BLOB字段中写数据，您只可以使用byte[]或InputStream或FormFile对象。");
		}
	}

	protected abstract void writeBLOB(ResultSet rs, Blob b, InputStream is)
			throws SQLException, IOException;

	/**
	 * 向CLOB字段中写数据
	 * 
	 * @param rs
	 *            已经定位到要写数据的那一行
	 * @param fieldName
	 *            字段名
	 * @param o
	 *            将要写入的数据，可以使用String、StringBuffer、char[]或Reader对象。不可以为null，否则将抛出SQLException异常。
	 * @throws SQLException
	 * @throws IOException
	 */
	public void writeCLOB(ResultSet rs, String fieldName, Object o)
			throws SQLException, IOException {
		if (o == null) {
			throw new SQLException("向CLOB字段中写数据，数据不可以是null。");
		}

		if (o instanceof String) {
			writeCLOB(rs, rs.getClob(fieldName), new StringReader((String) o));
		} else if (o instanceof StringBuffer) {
			writeCLOB(rs, rs.getClob(fieldName), new StringReader(
					(o.toString())));
		} else if (o instanceof char[]) {
			writeCLOB(rs, rs.getClob(fieldName),
					new CharArrayReader((char[]) o));
		} else if (o instanceof Reader) {
			writeCLOB(rs, rs.getClob(fieldName), (Reader) o);
		} else {
			throw new SQLException(
					"向CLOB字段中写数据，您只可以使用String、StringBuffer、char[]或Reader对象。");
		}
	}

	public void writeCLOB(ResultSet rs, int idx, Object o) throws SQLException,
			IOException {
		if (o == null) {
			throw new SQLException("向CLOB字段中写数据，数据不可以是null。");
		}

		if (o instanceof String) {
			writeCLOB(rs, rs.getClob(idx), new StringReader((String) o));
		} else if (o instanceof StringBuffer) {
			writeCLOB(rs, rs.getClob(idx), new StringReader((o.toString())));
		} else if (o instanceof char[]) {
			writeCLOB(rs, rs.getClob(idx), new CharArrayReader((char[]) o));
		} else if (o instanceof Reader) {
			writeCLOB(rs, rs.getClob(idx), (Reader) o);
		} else {
			throw new SQLException(
					"向CLOB字段中写数据，您只可以使用String、StringBuffer、char[]或Reader对象。");
		}
	}

	protected abstract void writeCLOB(ResultSet rs, Clob c, Reader rd)
			throws SQLException, IOException;

	public byte[] readBLOB(ResultSet rs, String fieldName) throws SQLException,
			IOException {
		return readBLOB(rs, rs.getBlob(fieldName));
	}

	public byte[] readBLOB(ResultSet rs, int idx) throws SQLException,
			IOException {
		return readBLOB(rs, rs.getBlob(idx));
	}

	protected abstract byte[] readBLOB(ResultSet rs, Blob b)
			throws SQLException, IOException;

	public char[] readCLOB(ResultSet rs, String fieldName) throws SQLException,
			IOException {
		return readCLOB(rs, rs.getClob(fieldName));
	}

	public char[] readCLOB(ResultSet rs, int idx) throws SQLException,
			IOException {
		return readCLOB(rs, rs.getClob(idx));
	}

	protected abstract char[] readCLOB(ResultSet rs, Clob c)
			throws SQLException, IOException;

}
